package von.seiji.cn.test;

import cn.hutool.core.lang.Dict;
import cn.hutool.core.map.MapUtil;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Map;
import java.util.Properties;
import java.util.function.Function;
import java.util.function.Predicate;

public class MapperUtil<T> {

    private Field[] fields;
    private T entity;

    public static <T> MapperUtil<T> builder(Class<T> clazz) {
        return new MapperUtil(clazz);
    }

    private MapperUtil(Class<T> clazz) {
        if (clazz != null) {
            this.fields = clazz.getDeclaredFields();
            try {
                this.entity = clazz.newInstance();
            } catch (Exception e) {
            }
        }
    }

    public T map2Bean(Map<String, Object> map, Dict mapping) {
        Arrays.stream(fields).forEach(item -> {
            String name = item.getName();
            item.setAccessible(true);
            String str = mapping.getStr(name);
            try {
                item.set(entity, MapUtil.get(map
                        , str, item.getType()));
            } catch (IllegalAccessException e) {
            }
            item.setAccessible(false);
        });
        return entity;
    }

    public T map2Bean(Map<String, Object> map, Properties properties) {
        Arrays.stream(fields).forEach(item -> {
            String name = item.getName();
            item.setAccessible(true);
            try {
                item.set(entity, MapUtil.get(map
                        , properties.getProperty(name), item.getType()));
            } catch (IllegalAccessException e) {
            }
            item.setAccessible(false);
        });
        return entity;
    }

    public T map2Bean(Map<String, Object> map, Properties properties, Predicate<Object> ignore) {
        Arrays.stream(fields).forEach(item -> {
            String name = item.getName();
            item.setAccessible(true);
            Object value = MapUtil.get(map
                    , properties.getProperty(name), item.getType());
            if (ignore.test(value)) {
                try {
                    item.set(entity, value);
                } catch (IllegalAccessException e) {
                }
            }
            item.setAccessible(false);
        });
        return entity;
    }


    public T map2Bean(Map<String, Object> map, Function<String, String> mapping) {
        Arrays.stream(fields).forEach(item -> {
            String name = item.getName();
            item.setAccessible(true);
            try {
                item.set(entity, MapUtil.get(map
                        , mapping.apply(name), item.getType()));
            } catch (IllegalAccessException e) {
            }
            item.setAccessible(false);
        });
        return entity;
    }


    public T map2Bean(Map<String, Object> map, Function<String, String> mapping, Predicate<Object> ignore) {
        Arrays.stream(fields).forEach(item -> {
            String name = item.getName();
            item.setAccessible(true);
            Object value = MapUtil.get(map
                    , mapping.apply(name), item.getType());
            if (ignore.test(value)) {
                try {
                    item.set(entity, value);
                } catch (IllegalAccessException e) {
                }
            }
            item.setAccessible(false);
        });
        return entity;
    }


}
